package io.gitee.jinceon.pmd.rules;

import net.sourceforge.pmd.RuleContext;
import net.sourceforge.pmd.lang.java.ast.*;
import net.sourceforge.pmd.lang.java.rule.AbstractJavaRule;

import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

public class ApiServiceRule extends AbstractJavaRule {
    private boolean isApiService = false;
    /**
     * 包名判断
     */
    @Override
    public Object visit(ASTPackageDeclaration node, Object data) {
        if(node.getName().endsWith(".api")){
            isApiService = true;
        }
        return null;
    }

    /**
     * apiService的method的返回值必须用R< > 包装
     */
    @Override
    public Object visit(ASTMethodDeclaration node, Object data) {
        if(!isApiService) {
            return null;
        }
        // 只检查 @Override的
        if(node.isAnnotationPresent("Override")){
            return null;
        }
        ASTResultType rt = node.getResultType();
        //  void =   /ResultType
        if(rt.isVoid()){
            asCtx(data).addViolationWithMessage(node, "apiService的method的返回值必须用R<>包装，void可以替换为R<Void>");
            return null;
        }
        ASTType type = (ASTType) rt.getChild(0);
        // int  =   /ResultType/Type/PrimitiveType

        if("char,boolean,byte,short,int,long,float,double".contains(type.getTypeImage())){
            String wrapName = Map.of(
                    "char", "Character",
                    "boolean", "Boolean",
                    "byte", "Byte",
                    "short", "Short",
                    "int", "Integer",
                    "long", "Long",
                    "float", "Float",
                    "double", "Double"
            ).get(type.getTypeImage());
            asCtx(data).addViolationWithMessage(node, "apiService的method的返回值必须用R<>包装，"+type.getTypeImage()+"可以替换为R<"+wrapName+">");
            return null;
        }
        // *    =   /ResultType/Type/ReferenceType/ClassOrInterfaceType
        String typeName = type.getType().getName();
        boolean returnWithR = typeName.equals("com.lightning.boot.base.vo.R");
        if (!returnWithR) {
            asCtx(data).addViolationWithMessage(node, "apiService的method的返回值必须用R<>包装，"+type.getTypeImage()+"可以替换成R<"+type.getTypeImage()+">");
        }

        return null;
    }
    @Override
    public void end(RuleContext ctx) {
        isApiService = false;
        super.end(ctx);
    }
}
